package com.zhentao.engine.impl;

import com.zhentao.engine.RuleEngine;
import com.zhentao.enums.RuleExecuteStatusEnum;
import com.zhentao.pojo.ParamRule;
import com.zhentao.vo.RuleExecuteResultVO;
import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import groovy.lang.Script;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * Groovy脚本规则引擎
 * @author zhentao
 * @date 2024-12-19
 */
@Slf4j
@Component
public class GroovyRuleEngine implements RuleEngine {

    private final GroovyShell groovyShell;

    public GroovyRuleEngine() {
        // 创建Groovy Shell，可以在这里添加安全配置
        this.groovyShell = new GroovyShell();
        log.info("Groovy规则引擎初始化完成");
    }

    @Override
    public RuleExecuteResultVO executeRule(ParamRule rule, Map<String, Object> inputData, Map<String, Object> context) {
        RuleExecuteResultVO result = new RuleExecuteResultVO();
        Date startTime = new Date();
        
        try {
            String groovyScript = rule.getConditionExpression();
            if (groovyScript == null || groovyScript.trim().isEmpty()) {
                result.setStatus(RuleExecuteStatusEnum.PARAM_ERROR.getCode());
                result.setMessage("Groovy脚本为空");
                return result;
            }
            
            // 创建绑定变量
            Binding binding = new Binding();
            
            // 绑定输入数据
            if (inputData != null) {
                for (Map.Entry<String, Object> entry : inputData.entrySet()) {
                    binding.setVariable(entry.getKey(), entry.getValue());
                }
            }
            
            // 绑定上下文数据
            if (context != null) {
                for (Map.Entry<String, Object> entry : context.entrySet()) {
                    binding.setVariable(entry.getKey(), entry.getValue());
                }
            }
            
            // 绑定常用工具类
            binding.setVariable("Math", Math.class);
            binding.setVariable("System", System.class);
            
            // 执行Groovy脚本
            // 创建新的Shell实例用于执行，使用binding
            GroovyShell shellWithBinding = new GroovyShell(binding);
            Object scriptResult = shellWithBinding.evaluate(groovyScript);
            
            // 处理执行结果
            Map<String, Object> resultData = new HashMap<>();
            resultData.put("result", scriptResult);
            resultData.put("script", groovyScript);
            resultData.put("resultType", scriptResult != null ? scriptResult.getClass().getSimpleName() : "null");
            
            result.setStatus(RuleExecuteStatusEnum.SUCCESS.getCode());
            result.setMessage("Groovy规则执行成功");
            result.setResultData(resultData);
            
            log.debug("Groovy规则执行成功: {} -> {}", rule.getRuleCode(), scriptResult);
            
        } catch (Exception e) {
            result.setStatus(RuleExecuteStatusEnum.ERROR.getCode());
            result.setMessage("Groovy规则执行失败: " + e.getMessage());
            result.setErrorCode("GROOVY_EXECUTION_ERROR");
            result.setErrorDetail(e.toString());
            log.error("Groovy规则执行失败: {}", rule.getRuleCode(), e);
        } finally {
            result.setEndTime(new Date());
            result.setExecutionTime(result.getEndTime().getTime() - startTime.getTime());
        }
        
        return result;
    }

    @Override
    public String validateRuleSyntax(String ruleContent, String engineType) {
        try {
            if (ruleContent == null || ruleContent.trim().isEmpty()) {
                return "Groovy脚本不能为空";
            }
            
            // 尝试解析Groovy脚本语法
            Script script = groovyShell.parse(ruleContent);
            if (script != null) {
                // 语法检查通过
                return null;
            } else {
                return "Groovy脚本解析失败";
            }
            
        } catch (Exception e) {
            return "Groovy脚本语法错误: " + e.getMessage();
        }
    }

    @Override
    public String getSupportedEngineType() {
        return "GROOVY";
    }

    @Override
    public int getPriority() {
        return 120; // 最高优先级
    }
}

